#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <ctype.h>

extern char** environ;

int my_execvp(const char* file, char* const argv[]) {
    if (strchr(file, '/')) {
        execve(file, argv, environ);
        return -1;
    }

    char* path_env = getenv("PATH");
    if (path_env == NULL) {
        fprintf(stderr, "PATH not found\n");
        return -1;
    }

    char* path_copy = strdup(path_env);
    char* dir = strtok(path_copy, ":");

    while (dir != NULL) {
        char full_path[1024];
        snprintf(full_path, sizeof(full_path), "%s/%s", dir, file);
        if (access(full_path, X_OK) == 0) {
            free(path_copy);
            execve(full_path, argv, environ);
            return -1;
        }
        dir = strtok(NULL, ":");
    }

    fprintf(stderr, "Command not found: %s\n", file);
    free(path_copy);
    return -1;
}

void execute_command(const char* cmd,
                     int is_first, int is_last,
                     int prev_fd, int pipefd[2],
                     int is_background)
{
    pid_t pid = fork();
    if (pid == 0)
    {
        // 子进程

        if (!is_first && prev_fd != -1) {
            dup2(prev_fd, STDIN_FILENO);
            close(prev_fd);
        }

        if (!is_last) {
            close(pipefd[0]);
            dup2(pipefd[1], STDOUT_FILENO);
            close(pipefd[1]);
        }

        // 拆分参数（处理为字符串存入数组）
        char cmd_copy[1024];
        strncpy(cmd_copy, cmd, sizeof(cmd_copy));
        char *args[64];
        int j = 0;

        char *ptr = strtok(cmd_copy, " ");
        while (ptr && j < 64)
        {
            args[j++] = ptr;
            ptr = strtok(NULL, " ");
        }
        args[j] = NULL;
       
        //单独处理每一个重定向
        char input_file[128] = {0};
        char output_file[128] = {0};
        int append_mode = 0; 
        
        for (int i = 0; args[i]; ++i) {
            if (strcmp(args[i], "<") == 0 && args[i+1]) {
                strncpy(input_file, args[i+1], sizeof(input_file));
            } else if (strcmp(args[i], ">>") == 0 && args[i+1]) {
                strncpy(output_file, args[i+1], sizeof(output_file));
                append_mode = 1;
            } else if (strcmp(args[i], ">") == 0 && args[i+1]) {
                strncpy(output_file, args[i+1], sizeof(output_file));
                append_mode = 0;
            }
        }

        //执行重定向
        if (is_first && input_file[0] != '\0') {
            int fd = open(input_file, O_RDONLY);
            if (fd < 0) {
                perror("open input failed");
                exit(1);
            }
            dup2(fd, STDIN_FILENO);
            close(fd);
        }

        if (is_last && output_file[0] != '\0') {
            int flags = O_WRONLY | O_CREAT | (append_mode ? O_APPEND : O_TRUNC);
            int fd = open(output_file, flags, 0644);
            if (fd < 0) {
                perror("open output failed");
                exit(1);
            }
            dup2(fd, STDOUT_FILENO);
            close(fd);
        }
        //构造去重定向符号后的数组
        char *pure_args[64];
        int k = 0;
        for (int i = 0; args[i] != NULL; ++i)
        {
            if ((strcmp(args[i], "<") == 0 || strcmp(args[i], ">") == 0 || strcmp(args[i], ">>") == 0) && args[i+1] != NULL)
            {
                ++i; // 跳过 filename
            }
            else
            {
                pure_args[k++] = args[i];
            }  
        }
        pure_args[k] = NULL;


        // 打印调试参数
        fprintf(stderr, "Running: ");
        for (int m = 0; pure_args[m]; ++m) fprintf(stderr, "[%s] ", pure_args[m]);
        fprintf(stderr, "\n");
        //执行用户命令
        my_execvp(pure_args[0], pure_args);
        perror("exec failed");
        exit(1);
    }

    if (pid > 0)
    {
        if (is_background)
            printf("[Background PID %d] %s\n", pid, cmd);
        else
            waitpid(pid, NULL, 0);
    }
}

void run_shell() {
    char command[1024];

    while (1) {
        // 显示当前路径
        char cwd[1024];
        if (getcwd(cwd, sizeof(cwd)) != NULL) {
            printf("[%s] myshell> ", cwd);
            fflush(stdout);
        } else {
            perror("getcwd failed");
        }

        if (fgets(command, sizeof(command), stdin) == NULL)
            continue;

        // 处理末尾空格与换行
        int len = strlen(command);
        while (len > 0 && isspace(command[len - 1])) len--;
        command[len] = '\0';  // 去除尾部空格或换行

        // 检查是否为后台执行
        int is_background = 0;
        if (len > 0 && command[len - 1] == '&') {
            is_background = 1;
            command[len - 1] = '\0';
        }

        // exit 命令退出 shell
        if (strcmp(command, "exit") == 0)
            break;

        //内建cd
        char command_copy[1024];
        strncpy(command_copy, command, sizeof(command_copy));

        char* first_token = strtok(command_copy, " ");
        if (first_token && strcmp(first_token, "cd") == 0)
        {
            char* path = strtok(NULL, " ");
            if (!path)
            {
                fprintf(stderr, "cd: missing operand\n");
            } 
            else if (chdir(path) != 0) 
            {
                perror("cd failed");
            }
            continue;  // 跳过执行阶段
        }  

        // 拆分管道
        char *cmds[10];
        int cmd_count = 0;
        char *token = strtok(command, "|");
        while (token && cmd_count < 10) {
            while (*token == ' ') token++;  // 去前导空格
            cmds[cmd_count++] = token;
            token = strtok(NULL, "|");
        }

        int prev_fd = -1;
        int pipefd[2];

        for (int i = 0; i < cmd_count; ++i) {
            if (i < cmd_count - 1 && pipe(pipefd) < 0) {
                perror("pipe failed");
                exit(1);
            }

            execute_command(cmds[i], i == 0, i == cmd_count - 1,
                            prev_fd, pipefd, is_background);

            if (prev_fd != -1) close(prev_fd);
            if (i < cmd_count - 1) {
                close(pipefd[1]);
                prev_fd = pipefd[0];
            }
        }
    }
}

